import logging

from flask import make_response, abort

from ..validator.util import paramsValidator
from ..views import make_hal_response


class BaseController:
    """Base Controller:

    Attr:
        validator
        processor
        document
        collection

    def d(self, document):    # document
        pass

    def c(self, collection):  # collection
        pass

    function:
        post
        get
        head
        put
        patch
        delete
    """
    CREATE = 'create'
    READ = 'read'
    UPDATE = 'update'
    DELETE = 'delete'

    def serialize(self, payload):
        print("*"*80, "serialize")
        print(repr(payload))
        print("*"*80, "serialize")
        # collection
        if isinstance(payload, list) and hasattr(self, 'collection'):
            try:
                if hasattr(self, 'c'):
                    payload = self.c(payload)
                return self.collection.serialize(payload)
            except Exception as e:
                print("serialize:Exception: %r" % e)
                pass
        if hasattr(self, 'document'): # document
            try:
                if hasattr(self, 'd'):
                    payload = self.d(payload)
                return self.document.serialize(payload)
            except Exception as e:
                print("serialize:Exception: %r" % e)
                pass
        return payload

    @paramsValidator()
    def post(self, *args, **kwargs):
        """paramsValidator for kwargs
        """
        fn = getattr(self.processor, self.CREATE)
        rv = fn(*args, **kwargs)
        if rv is True:
            return make_response('', 202)
        serialized = self.serialize(rv)
        return make_hal_response(serialized, 201)

    def get(self, *args, **kwargs):
        fn = getattr(self.processor, self.READ)
        print("B"*80)
        print(repr(fn))
        print("B"*80)
        rv = fn(*args, **kwargs)
        if not rv:
            abort(404)
        serialized = self.serialize(rv)
        return make_hal_response(serialized)

    def head(self, *args, **kwargs):
        raise NotImplementedError

    def put(self, *args, **kwargs):
        raise NotImplementedError

    def patch(self, *args, **kwargs):
        fn = getattr(self.processor, self.UPDATE)
        rv = fn(*args, **kwargs)
        if rv is True:
            return make_response('', 202)
        serialized = self.serialize(rv)
        return make_hal_response(serialized)

    def delete(self, *args, **kwargs):
        fn = getattr(self.processor, self.DELETE)
        rv = fn(*args, **kwargs)
        if rv is False:
            abort(406)
        return make_response('', 204)
